<?php
/**
 * Hearth of the CMS
 *
 * @author Martin "DevelX" Jurča
 * @version 2010-05-18
 */
class Kernel {
    const DISPLAY = 0;
    const ADMIN = 1;
    const EVENT = 2;

    private static $mode;
    private static $ajax;
    private static $redirectUrl = null;

    private function __construct() {}

    public static function init() {
        if (Config::AUTODETECT_SESSION_LANG && !isset($_SESSION['language'])) {
            self::detectLanguage();
        }
        if (Config::AUTODETECT_SESSION_CHARSET &&
                !isset($_SESSION['charset'])) {
            self::detectCharset();
        }
        setlocale(LC_ALL, "en_US.UTF8");
        if (Config::INSTALLED) {
            self::loadLibraries();
            self::conver2UTF8($_GET);
            self::conver2UTF8($_POST);
            self::$ajax = isset($_GET['ajax']) || isset($_POST['ajax']);
            if ((isset($_GET['mode']) && ($_GET['mode'] == 'event')) ||
                    (isset($_POST['mode']) && ($_POST['mode'] == 'event'))) {
                return self::initEvent();
            } elseif (isset($_GET['mode']) && ($_GET['mode'] == 'admin')) {
                return self::initAdmin();
            } else {
                return self::initDisplay();
            }
        } else {
            return self::initInstall();
        }
    }

    private static function initInstall() {
        require_once dirname(__FILE__) . '/../install/Installer.php';
        try {
            new Installer();
        } catch (Exception $e) {
            return false;
        }
        return true;
    }

    private static function initDisplay() {
        self::$mode = self::DISPLAY;
        header('Content-Type: text/html; charset=' . self::getCharset());
        require_once Config::ROOT . '/libs/smarty/Smarty.class.php';
        Modules::getModule('Log');
        Modules::getModule('View')->display();
        FTP::close();
        return true;
    }

    private static function initAdmin() {
        self::$mode = self::ADMIN;
        header('Content-Type: text/html; charset=' . self::getCharset());
        require_once Config::ROOT . '/libs/smarty/Smarty.class.php';
        Modules::getModule('Log');
        Modules::getModule('View')->display();
        FTP::close();
        return true;
    }

    private static function initEvent() {
        self::$mode = self::EVENT;
        Modules::getModule('Log');
        $event = isset($_POST['event']) ? $_POST['event'] : $_GET['event'];
        $details = count($_POST) > 0 ? $_POST :
                (isset($_GET['url']) ? $_GET['url'] : '');
        $source = isset($_POST['source']) ? $_POST['source'] :
                (isset($_GET['source']) ? $_GET['source'] : '');
        $target = isset($_POST['target']) ? $_POST['target'] :
                (isset($_GET['target']) ? $_GET['target'] : '');
        $source = Modules::resolveModuleUrl($source);
        $target = Modules::resolveModuleUrl($target);
        Modules::fireEvent($event, $details, $source, $target);

        if (self::$redirectUrl != null) {
            header('Location: ' . self::$redirectUrl);
            FTP::close();
            return true;
        }
        if (isset($_GET['mode'])) {
            unset($_GET['mode']);
        }
        if (isset($_POST['mode'])) {
            unset($_POST['mode']);
        }
        if (isset($_GET['inAdmin']) || isset($_POST['inAdmin'])) {
            $_GET['mode'] = 'admin';
        }
        FTP::close();
        return self::init();
    }

    public static function setLanguage($language) {
        if ((preg_match('/^\w{2}$/', $language) == 0) &&
                (preg_match('/^\w{2}-\w{2}$', $language))) {
            $_SESSION['language'] = $language;
            return true;
        }
        return false;
    }

    public static function getLanguage() {
        if (isset($_SESSION['language'])) {
            return $_SESSION['language'];
        } else {
            return Config::DEFAULT_LANG;
        }
    }

    public static function setCharset($charset) {
        if (iconv('UTF-8', $charset, 'abcd') !== false) {
            $_SESSION['charset'] = $charset;
            return true;
        }
        return false;
    }

    public static function getCharset() {
        if (isset($_SESSION['charset'])) {
            return $_SESSION['charset'];
        } else {
            return Config::DEFAULT_CHARSET;
        }
    }

    public static function getMode() {
        return self::$mode;
    }

    public static function isAJAXMode() {
        return self::$ajax;
    }

    public static function createUrl($rawString) {
        $url = iconv('utf-8', 'ASCII//TRANSLIT', $rawString);
        $url = preg_replace('/[\W]/', '-', $url);
        return preg_replace('/[-]{2,}/', '-', $url);
    }

    public static function getImageLink(&$parameters) {
        return Config::WEB_DIR . '/utils/image.php?serialized=' .
                urlencode(serialize($parameters));
    }

    public static function getSimpleImageLink($id, $width, $height,
            $border = false) {
        return Config::WEB_DIR . "/utils/simage.php?i=$id|$width|$height" .
                ($border ? '|1' : '');
    }

    public static function setRedirect($url) {
        if (self::$mode == self::EVENT) {
            self::$redirectUrl = $url;
        }
    }

    /**
     * Loads basic libraries, basic module interface and module loader.
     *
     */
    private static function loadLibraries() {
        require_once Config::ROOT . '/libs/Cache.php';
        require_once Config::ROOT . '/libs/FTP.php';
        require_once Config::ROOT . '/libs/DBDriver' .
                Config::DATABASE_DRIVER . '.php';
        require_once Config::ROOT . '/libs/DBAPI.php';
        require_once Config::ROOT . '/libs/RecordList.php';
        require_once Config::ROOT . '/modules/Module.php';
        require_once Config::ROOT . '/modules/Modules/Modules.php';
    }

    /**
     * Converts array of strings or string to system inner encoding (UTF-8).
     * The method preserves uncovertable values.
     *
     * @param mixed $input Array or string to convert.
     */
    private static function conver2UTF8(&$input) {
        if (is_array($input)) {
            foreach ($input as $key => &$value) {
                self::conver2UTF8($value);
            }
        } elseif (is_string($input)) {
            $input = @iconv(Kernel::getCharset(), 'utf-8', $input);
        }
    }

    /**
     * Detects the output charset from data read from Accept-Charset HTTP
     * header.
     *
     */
    private static function detectCharset() {
        if (!isset($_SERVER['HTTP_ACCEPT_CHARSET'])) {
            $_SESSION['charset'] = Config::DEFAULT_CHARSET;
            return;
        }
        $charsets = preg_split('/[,;]/', $_SERVER['HTTP_ACCEPT_CHARSET']);
        foreach ($charsets as $id => &$charset) {
            $charset = trim($charset);
            if (strtolower($charset) == 'utf-8') {
                $_SESSION['charset'] = $charset;
                return;
            }
            if (($charset == '*') || (substr($charset, 0, 2) == 'q=')) {
                unset($charsets[$id]);
            }
        }
        $keys = array_keys($charsets);
        $_SESSION['charset'] = $charsets[$keys[0]];
    }

    /**
     * Detects the language from data read from Accept-Language HTTP header.
     *
     */
    private static function detectLanguage() {
        if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
            $_SESSION['language'] = Config::DEFAULT_LANG;
            return;
        }
        $languages = preg_split('/[,;]/', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
        foreach ($languages as $id => &$language) {
            $language = trim($language);
            if (($language == '*') || (substr($language, 0, 2) == 'q=')) {
                unset($languages[$id]);
            }
        }
        $keys = array_keys($languages);
        $_SESSION['language'] = $languages[$keys[0]];
    }
}
?>
